package cn.iocoder.yudao.module.scrm.aop;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.framework.excel.core.strategy.DictTenantContext;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.scrm.annotations.DictField;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.List;

@Aspect
@Component
@Slf4j
public class DictionaryAspect {

    /**
     * 在控制器方法返回后进行处理
     *
     * @param joinPoint 切入点
     * @param result    方法返回结果
     */
    @AfterReturning(pointcut = "execution(* cn.iocoder.yudao.module.scrm.controller..*Controller.*(..))", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        if (result instanceof CommonResult) {
            processResult(((CommonResult<?>) result).getData());
        }
    }

    /**
     * 处理返回结果
     *
     * @param data 返回的数据
     */
    private void processResult(Object data) {
        if(ObjectUtils.isEmpty(data)) {
            return;
        }
        if (data instanceof PageResult) {
            processPageResult((PageResult<?>) data);
        } else {
            processObject(data);
        }
    }

    /**
     * 处理分页结果
     *
     * @param pageResult 分页结果
     */
    private void processPageResult(PageResult<?> pageResult) {
        List<?> list = pageResult.getList();
        if (!ObjectUtils.isEmpty(list)) {
            list.forEach(this::processObject);
        }
    }

    /**
     * 处理对象中的字段
     *
     * @param obj 要处理的对象
     */
    private void processObject(Object obj) {
        Field[] fields = obj.getClass().getDeclaredFields(); // 缓存字段数组
        for (Field field : fields) {
            if (field.isAnnotationPresent(DictField.class)) {
                processField(obj, field);
            }
        }
    }

    /**
     * 处理单个字段
     *
     * @param obj   包含该字段的对象
     * @param field 要处理的字段
     */
    private void processField(Object obj, Field field) {
        try {
            field.setAccessible(true); // 确保字段可以访问
            Object value = field.get(obj);
            if (isInteger(value)) {
                handleIntegerField(obj, field, (Integer) value);
            }else if (value instanceof String) {
                try {
                    Integer intValue = Integer.parseInt((String) value);
                    handleIntegerField(obj, field, intValue);
                } catch (NumberFormatException e) {
                    log.warn("字段 {} 的值 {} 不能转换为Integer类型，请检查传入的字典值是否有误", field.getName(), value);
                }
            }  else {
                log.warn("字段 {} 的值 {} 不是Integer类型，无法转换为字典标签", field.getName(), value);
            }
        } catch (IllegalAccessException e) {
            log.error("访问字段 {} 时出现 IllegalAccessException: {}", field.getName(), e.getMessage());
        } catch (Exception e) {
            log.error("处理字段 {} 时出现异常: {}", field.getName(), e.getMessage());
        }
    }


    /**
     * 检查字段值是否为整数类型
     *
     * @param value 字段值
     * @return 如果是整数类型返回 true，否则返回 false
     */
    private boolean isInteger(Object value) {
        return value instanceof Integer;
    }

    /**
     * 处理整数类型的字段
     *
     * @param obj   包含该字段的对象
     * @param field 要处理的字段
     * @param code  字典代码
     */
    private void handleIntegerField(Object obj, Field field, Integer code) {
        //String label = DictFrameworkUtils.getDictDataLabel(field.getAnnotation(DictField.class).dictType(), code);
        //兼容在同一字段使用不同字典得情况-卓越的租户用带zy的字典
        Long tenantId = TenantContextHolder.getTenantId();
        //使用不同租户对应不同策略
        DictTenantContext tenantContext = new DictTenantContext(Math.toIntExact(tenantId));
        String label = tenantContext.getDictDataLabel(field.getAnnotation(DictField.class).dictType(), code);
        if (label != null) {
            setLabelField(obj, field, label);
        } else {
            log.warn("未找到字段 {} 的字典标签，类型为 {}", field.getName(), field.getAnnotation(DictField.class).dictType());
        }
    }

    /**
     * 设置标签字段的值
     *
     * @param obj       包含该字段的对象
     * @param field     要处理的字段
     * @param label     字典标签
     */
    private void setLabelField(Object obj, Field field, String label) {
        try {
            String labelFieldName = field.getName() + "Label";
            Field labelField = obj.getClass().getDeclaredField(labelFieldName);
            labelField.setAccessible(true); // 确保标签字段可以访问
            labelField.set(obj, label);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            log.error("设置标签字段 {} 时出现异常: {}", field.getName() + "Label", e.getMessage());
        }
    }
}
